﻿using System;

using BodaNetCommunications.Utilities.Results;
using BodaNetCommunications.Utilities.Tools;

namespace BodaNetCommunications.ModbusTcpComs
{
    /// <summary>
    /// Modbus协议相关的一些信息
    /// </summary>
    public class ModbusInfo
    {
        #region ErrCode Declaration

        /// <summary>
        /// 不支持该功能码
        /// </summary>
        public const byte FunctionCodeNotSupport = 0x01;

        /// <summary>
        /// 该地址越界
        /// </summary>
        public const byte FunctionCodeOverBound = 0x02;

        /// <summary>
        /// 读取长度超过最大值
        /// </summary>
        public const byte FunctionCodeQuantityOver = 0x03;

        /// <summary>
        /// 读写异常
        /// </summary>
        public const byte FunctionCodeReadWriteException = 0x04;

        #endregion ErrCode Declaration

        #region Static Helper Method

        /// <summary>
        /// 将modbus指令打包成Modbus-Tcp指令
        /// </summary>
        /// <param name="value">Modbus指令</param>
        /// <param name="id">消息的序号</param>
        /// <returns>Modbus-Tcp指令</returns>
        public static byte[] PackCommandToTcp(byte[] value, ushort id)
        {
            byte[] buffer = new byte[value.Length + 6];
            buffer[0] = BitConverter.GetBytes(id)[1];
            buffer[1] = BitConverter.GetBytes(id)[0];

            buffer[4] = BitConverter.GetBytes(value.Length)[1];
            buffer[5] = BitConverter.GetBytes(value.Length)[0];

            value.CopyTo(buffer, 6);
            return buffer;
        }

        /// <summary>
        /// 分析Modbus协议的地址信息，该地址适应于tcp及rtu模式 >>>
        /// 1. 支持富地址，例如s=2;x=3;100
        /// 2. 注意： 对于多地址的写入，需要具体指定功能码
        /// </summary>
        /// <param name="address">带格式的地址，比如"100"，"x=4;100"，"s=1;100","s=1;x=4;100"</param>
        /// <param name="isStartWithZero">起始地址是否从0开始</param>
        /// <param name="defaultFunction">默认的功能码信息</param>
        /// <returns>转换后的地址信息</returns>
        public static BodaResult<ModbusAddress> AnalysisAddress(string address, bool isStartWithZero, ModbusFunctionCode defaultFunction)
        {
            try
            {
                ModbusAddress mAddress = new ModbusAddress(address, defaultFunction);
                if (!isStartWithZero)
                {
                    if (mAddress.Address < 1) throw new Exception(StringResources.Language.ModbusAddressMustMoreThanOne);
                    mAddress.Address = (ushort)(mAddress.Address - 1);
                }
                return BodaResult.CreateSuccessResult(mAddress);
            }
            catch (Exception ex)
            {
                return new BodaResult<ModbusAddress>() { Message = ex.Message };
            }
        }

        /// <summary>
        /// 通过错误码来获取到对应的文本消息
        /// </summary>
        /// <param name="code">错误码</param>
        /// <returns>错误的文本描述</returns>
        public static string GetDescriptionByErrorCode(byte code)
        {
            switch (code)
            {
                case ModbusInfo.FunctionCodeNotSupport: return StringResources.Language.ModbusTcpFunctionCodeNotSupport;
                case ModbusInfo.FunctionCodeOverBound: return StringResources.Language.ModbusTcpFunctionCodeOverBound;
                case ModbusInfo.FunctionCodeQuantityOver: return StringResources.Language.ModbusTcpFunctionCodeQuantityOver;
                case ModbusInfo.FunctionCodeReadWriteException: return StringResources.Language.ModbusTcpFunctionCodeReadWriteException;
                default: return StringResources.Language.UnknownError;
            }
        }

        #endregion Static Helper Method
    }
}